﻿#include "NetWork.h"
#include <iostream>
#include <QTcpSocket>
#include <QHostAddress>
#include <QKeyEvent>
#include <QEvent>
#include <StdClassFun.h>
#include <ThreadCin.h>
#include <ThreadClienNetWork.h>

bool NetWork::event(QEvent* event) {
	return QApplication::event(event);
}

NetWork::NetWork(int& argc
	, char** argv
	, int i): QApplication{ argc,argv,i } {
	ioMutex = new QMutex;
}

NetWork::~NetWork( ) {
	//
	auto&& clientInstanSize = clienConnectVector.size( );
	for( int index = 0;index < clientInstanSize;++index ) {
		delete clienConnectVector[index];
	}
	if( serverInstance ) {
		delete serverInstance;
	} else {
		// 释放 目标对象
		int size = targetObjs.size( );
		for( int index = 0;index < size;++index )
			delete targetObjs[index];
	}
	if(threadCin)
		delete threadCin;
	delete ioMutex;
}

void NetWork::appRunParameter(QString& key
	, QVector<QString>& value) {
	QVector<QString> mapValue = parameter.value(key);
	mapValue.append(value);
	parameter.insert(key, mapValue);
}

void NetWork::initClientSocket(QTcpSocket* clienInstance
	, const QString& ip
	, const QString& prot
	, int& iProt) {
	connect(clienInstance, &QTcpSocket::connected, this, &NetWork::clientConnected);
	void (QAbstractSocket::*errorFunp)(QAbstractSocket::SocketError) = &QTcpSocket::error;
	connect(clienInstance, errorFunp, this, &NetWork::clientError);
	connect(clienInstance, &QTcpSocket::hostFound, this, &NetWork::clientHostFound);
	connect(clienInstance, &QTcpSocket::disconnected, this, &NetWork::clientDisconnected);
	connect(clienInstance, &QTcpSocket::stateChanged, this, &NetWork::clientStateChanged);
	connect(clienInstance, &QTcpSocket::readyRead, this, &NetWork::readyRead);
	std::cout << QString("开始链接--->\t目标\t" + ip + " : " + prot).toLocal8Bit( ).constData( ) << std::endl;
	clienInstance->connectToHost(ip, iProt);
	clienConnectVector.append(clienInstance);
}

int NetWork::runNetWork( ) {
	if( parameter.contains("-server") ) {
		// 生成服务器
		serverInstance = new QTcpServer;
		auto protParam = parameter.value("-server")[0];
		bool isOk = false;
		int port = protParam.toInt(&isOk);
		if( !isOk ) {
			std::cout << QString("发现参数异常，请重启程序\t").toLocal8Bit( ).constData( ) << std::endl;
			return -1;
		}
		if( ! serverInstance->listen(QHostAddress::Any, port) ) {
			std::cout << QString("服务器启动失败，请检查配置\t" + protParam).toLocal8Bit( ).constData( ) << std::endl;
			return -1;
		}
		std::cout << QString("允许被链接到端口\t" + protParam).toLocal8Bit( ).constData( ) << std::endl;
		connect(serverInstance, &QTcpServer::newConnection, this, &NetWork::serverNewConnection);
		connect(serverInstance, &QTcpServer::acceptError, this, &NetWork::serverAcceptError);
	}
	if( parameter.contains("-client") ) {
		// 链接服务器
		const QVector<QString> vector = parameter.value("-client");
		for( int index = 0, clientParames = vector.size( );index < clientParames;++index ) {
			QTcpSocket* clienInstance = new QTcpSocket;
			auto&& ip = vector.at(index);
			if( !ip.contains(':') ) {
				++index;
				auto&& prot = vector.at(index);
				bool converOnk = false;
				auto&& iProt = prot.toInt(&converOnk);
				if( !converOnk ) {
					delete clienInstance;
					std::cout << QString("参数获取失败，请检查配置\t" + ip + " : " + prot).toLocal8Bit( ).constData( ) << std::endl;
					continue;
				}
				initClientSocket(clienInstance, ip, prot, iProt);
				continue;
			}
			QStringList list = ip.split(':');
			bool converOnk = false;
			if( list.size( ) != 2 ) {
				delete clienInstance;
				std::cout << QString("参数获取失败，请检查配置\n参数为 = \n\t\" " + ip + " \"").toLocal8Bit( ).constData( ) << std::endl;
				continue;
			}
			QString& ipTarget = list[0];
			QString& protParam = list[1];
			auto&& iProt = protParam.toInt(&converOnk);
			if( !converOnk ) {
				delete clienInstance;
				std::cout << QString("参数获取失败，请检查配置\t" + ipTarget + " : " + protParam).toLocal8Bit( ).constData( ) << std::endl;
				continue;
			}
			initClientSocket(clienInstance, ipTarget, protParam, iProt);
		}
	}
	if( clienConnectVector.size( ) > 0 || serverInstance ) {
		threadCin = new ThreadCin(&targetObjs, ioMutex);
		connect(threadCin, &ThreadCin::getCin, this, &NetWork::getCin);
		// 启动输入
		threadCin->start( );
		return exec( );
	}
	return 0;
}

void NetWork::serverNewConnection( ) {
	while( serverInstance->hasPendingConnections( ) ) {
		// 获取客户端
		QMutexLocker locker(ioMutex);
		QTcpSocket* clientConnection = serverInstance->nextPendingConnection( );
		QHostAddress address = clientConnection->peerAddress( );
		std::cout << ( "发现地址\t" + address.toString( ) ).toLocal8Bit( ).constData( ) << std::endl;
		connect(clientConnection, &QTcpSocket::readyRead, this, &NetWork::readyRead);
		targetObjs.append(new ThreadClienNetWork(clientConnection));
	}
}

void NetWork::getCin(QString* str
	, QSemaphore* qSemaphore) {
	QString string = *str;
	auto&& size = targetObjs.size( );
	for( int index = 0;index < size;++index )
		targetObjs[index]->sendMsg(str, qSemaphore);
}

void NetWork::serverAcceptError(QAbstractSocket::SocketError socketError) {}

void NetWork::clientHostFound( ) {}

void NetWork::clientConnected( ) {
	targetObjs.append(new ThreadClienNetWork(qobject_cast<QTcpSocket*>(sender( ))));
}

void NetWork::clientDisconnected( ) {}

void NetWork::clientStateChanged(QAbstractSocket::SocketState) {}

void NetWork::clientError(QAbstractSocket::SocketError) {}

void NetWork::readyRead( ) {
	QTcpSocket* tcpSocket = qobject_cast<QTcpSocket*>(sender( ));
	QByteArray byteArray = tcpSocket->readAll( );
	QString string = QString::fromLocal8Bit(byteArray.data( ));
	QString buff;
	buff.append("ip:" + tcpSocket->peerAddress( ).toString( ) + "\n");
	buff.append("port:" + QString("%1").arg(tcpSocket->peerPort( )) + "\n");
	buff.append("msg:" + string + "\n");
	std::cout << buff.toLocal8Bit( ).constData( ) << std::endl;
}
